package de.zainodis.authorlist.model.parsing;

import static junit.framework.Assert.assertNotNull;

import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import de.zainodis.authorlist.model.AuthorsCreation;

public abstract class AuthorsCreationParser<T extends AuthorsCreation> extends XmlFeedParser<T> {

   protected static final String KEY_TITLE = "titel";
   protected static final String KEY_PRICE = "price";
   protected static final String KEY_ISBN = "isbn";
   /** Author elements are embedded in an array element */
   protected static final String KEY_AUTHOR = "author";

   /** The beginning of a new entry */
   protected static final String ENTRY_ELEMENT = "dict";

   private T underConstruction;

   private Collection<String> authors;

   private String nextKey;

   /** Some values are embedded in an array element */
   private boolean parsingArray = false;

   @Override
   public void handleStartTag(String name, XmlPullParser parser) throws XmlPullParserException,
	    IOException {
	 if (ENTRY_ELEMENT.equals(name)) {
	    underConstruction = createNew();

	 } else if (KEY_ELEMENT.equals(name)) {
	    // The text node contains the key name
	    nextKey = parser.nextText();

	 } else if (isParsing()) {
	    // It's a value attribute of the book
	    assertNotNull("Each value must be preceeded by a key.", nextKey);

	    if (parsingArray) {
		  // We're currently parsing authors, read the authors name
		  authors.add(parser.nextText());
	    } else if (ARRAY_ELEMENT.equals(name)) {
		  // We've started parsing the authors
		  parsingArray = true;
		  // Start new set of authors
		  authors = new HashSet<String>();
	    } else if (KEY_TITLE.equals(nextKey)) {
		  underConstruction.setTitle(parser.nextText());
	    } else if (KEY_PRICE.equals(nextKey)) {
		  underConstruction.setPrice(parser.nextText());
	    } else if (KEY_ISBN.equals(nextKey)) {
		  underConstruction.setIsbn(parser.nextText());
	    }
	 }
   }

   @Override
   public void handleEndTag(String name, XmlPullParser parser) throws XmlPullParserException,
	    IOException {

	 if (ENTRY_ELEMENT.equals(name)) {
	    // Add the parsed item to the result set
	    addItem(underConstruction);
	    // Reset parsed item
	    underConstruction = null;
	    nextKey = null;
	    authors = null;
	 } else if (isParsing()) {
	    if (ARRAY_ELEMENT.equals(name)) {
		  // We're done parsing authors
		  underConstruction.setAuthors(authors);
		  parsingArray = false;
		  authors = null;
	    }
	 }
   }

   public String getNextKey() {
	 return nextKey;
   }

   protected boolean isParsing() {
	 return underConstruction != null;
   }

   public boolean isParsingArray() {
	 return parsingArray;
   }

   protected abstract T createNew();

   public T getUnderConstruction() {
	 return underConstruction;
   }
}
